package com.java.basis.io.nio.one;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

/**
 * 目标：NIO非阻塞通信入门案例，服务端开发
 *
 * @author wangning
 * @create 2022-01-11 11:26
 */
public class Server {
	public static void main(String[] args) throws Exception {
		System.out.println("---服务端启动---");
		//1.获取通道
		ServerSocketChannel ssChannel = ServerSocketChannel.open();
		//2.切换成非阻塞式模式
		ssChannel.configureBlocking(false);
		//3.绑定连接的端口
		ssChannel.bind(new InetSocketAddress(9999));
		//4.获取选择器Selector
		Selector selector = Selector.open();
		//5.将通道都注册到选择器上去，并且开始指定监听接收事件
		ssChannel.register(selector, SelectionKey.OP_ACCEPT);
		//6.使用selector选择器轮询已经就绪好的事件
		while (selector.select() > 0) {
			System.out.println("开始一轮事件处理---");
			//7.获取选择器中的所有注册到通道中已经就绪的事件
			Iterator<SelectionKey> it = selector.selectedKeys().iterator();
			//8.开始遍历这些准备好的事件
			while (it.hasNext()) {
				//提取当前事件
				SelectionKey sk = it.next();
				//9.判断这个事件具体是什么
				if(sk.isAcceptable()) {
					//10.直接获取当前接入的客户端通道
					SocketChannel sChannel = ssChannel.accept();
					//11.设置成非阻塞式通道
					sChannel.configureBlocking(false);
					//12.将本客户端通道注册到选择器
					sChannel.register(selector, SelectionKey.OP_READ);
				} else if(sk.isReadable()) {
					//13.获取当前选择器上读就绪事件
					SocketChannel sChannel = (SocketChannel) sk.channel();
					//14.读取数据
					ByteBuffer buffer = ByteBuffer.allocate(1024);
					int len = 0;
					while ((len = sChannel.read(buffer)) > 0) {
						buffer.flip();
						System.out.println(new String(buffer.array(), 0, len));
						buffer.clear();//这里的清除并不是真正的清除，而是让缓冲区的位置归于开始位置
					}
				}
				//处理完毕需要移除当前操作
				it.remove();
			}
		}

	}
}
